<?php


namespace BoojasrFramework\DependencyInjection\Compiler;


use BoojasrFramework\ServicesContainer\ContainerBuilder;
use BoojasrFramework\ServicesContainer\DependencyInjection\Compiler\CompilerPassInterface;
use BoojasrFramework\ServicesContainer\EventDispatcher\EventSubscriberInterface;

class RegisteredEventPass implements CompilerPassInterface
{

    /**
     * @param ContainerBuilder $container
     */
    public function process(ContainerBuilder $container)
    {
        if (!$container->hasDefinition("event_dispatcher")){
            return ;
        }

        $globalDispatcherDefinition = $container->getDefinition("event_dispatcher");
        $taggedServices = $container->findTaggedServiceIds('event_subscriber',true);

        foreach ($taggedServices as $id=>$event){
            $priority = isset($event['priority']) ?$event["priority"]: 0;

            $dispatcherDefinition = $globalDispatcherDefinition;
            if (isset($event['dispatcher'])) {
                $dispatcherDefinition = $container->getDefinition($event['dispatcher']);
            }

            $eventSubscriber = $container->get($id);
            if ($eventSubscriber instanceof EventSubscriberInterface){
                $dispatcherDefinition->addMethodCall("addSubscriber",[$eventSubscriber]);
            }else if ($eventSubscriber){
                if (!isset($event['method'])) {
                    $event['method'] = 'on'.preg_replace_callback([
                            '/(?<=\b|_)[a-z]/i',
                            '/[^a-z0-9]/i',
                        ], function ($matches) { return strtoupper($matches[0]); }, $event['event']);
                    $event['method'] = preg_replace('/[^a-z0-9]/i', '', $event['method']);

                    if (null !== ($class = $container->getDefinition($id)->getClass()) && ($r = $container->getReflectionClass($class)) && !$r->hasMethod($event['method']) && $r->hasMethod('__invoke')) {
                        $event['method'] = '__invoke';
                    }
                }

                $dispatcherDefinition->addMethodCall('addListener', [$event['event'], [$eventSubscriber, $event['method']], $priority]);
            }
        }

    }
}
